package com.trsvax.gwthello.components;

import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.RenderSupport;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.ClientBehaviorSupport;
import org.slf4j.Logger;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.rpc.RemoteService;

public abstract class GWTComponent<G extends EntryPoint, S extends RemoteService> {

	@Inject
	private Logger logger;

	@Environmental
	private RenderSupport pageRenderSupport;
	@Environmental
	private ClientBehaviorSupport clientBehaviorSupport;

	@Inject
	private ComponentResources componentResources;

	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	private String zone;

	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	private String event;

	public String getType() {
		return this.getClass().getCanonicalName().replace(".", "-");
	}

	public String getClientID() {
		return componentResources.getId();
	}

	public String getCompleteID() {
		String path = componentResources.getCompleteId().replaceFirst(":", "?");
		logger.info("completeid {} {}", componentResources.getCompleteId(), path);
		return componentResources.getCompleteId().replaceFirst(":", "?");
	}

	// because G.class is not easy
	public abstract Class<G> getGWTModuleClass();

	public String getGWTName() {
		return getGWTModuleClass().getName().replace(".", "");
	}

	public String getZone() {
		if (zone == null)
			return "";
		return "zone: \"" + zone + "\",";
	}

	void beginRender(MarkupWriter writer) {
		if (zone != null) {
			clientBehaviorSupport.addZone(zone, null, null);
		}

	}

	void afterRender(MarkupWriter writer) {
		String ajaxString = getGWTName() + ".componentIDs += \"" + getClientID() + ",\"";
		pageRenderSupport.addScript(ajaxString);

	}

	@SuppressWarnings("unchecked")
	public S getContainer() {
		return (S) componentResources.getContainer();
	}

}
